import { unset } from 'lodash-es'
import dayjs from 'dayjs'

export interface ListToOptFilters {
  label: string
  value: string
}

export const tools = {
  listToTree(
    list: any[],
    options: { pid: string; id?: string; children?: string } = {
      pid: 'parentId',
      id: 'id',
      children: 'children'
    }
  ) {
    const { pid, id = 'id', children = 'children' } = options
    const listMap = new Map()
    const result: any[] = []

    list.forEach((item) => {
      listMap.set(item[id], item)
    })

    list.forEach((item) => {
      const parent = listMap.get(item[pid])
      if (parent) {
        parent[children] = parent[children] || []
        parent[children].push(item)
      } else {
        result.push(item)
      }
    })

    return result
  },
  treeToList(tree: any[], options?: { children: string }) {
    const { children } = options || { children: 'children' }
    const result: any[] = []

    function traverse(node: any) {
      const nodeChildren = node[children]
      unset(node, children)

      result.push(node)
      if (nodeChildren && nodeChildren.length > 0) {
        nodeChildren.forEach((child: any) => traverse(child))
      }
    }

    tree.forEach((node) => traverse(node))

    return result
  },
  /** 日期格式转换 */
  dateFormat(date: string | Date, format: string = 'YYYY-MM-DD HH:mm:ss') {
    return date && dayjs(date).format(format)
  },
  /**
   * 将列表转换为选项格式
   *
   * 此函数用于将一个列表对象数组转换成带有标签和值的选项格式，通常用于UI组件如 dropdown 的数据源
   * 它根据指定的过滤条件来确定每个选项的标签和值
   *
   * @param lst 输入的列表对象数组，每个对象通常代表一个条目
   * @param isOrigin 选项是否包含源数据
   * @param listToOptFilters 过滤条件对象，指定如何从每个列表对象中提取标签和值的属性名
   * @returns 返回一个对象数组，每个对象包含原始数据和转换后的标签和值属性
   */
  listToOptions<T>(
    lst: Record<string, any>[],
    listToOptFilters: ListToOptFilters = { label: 'dictName', value: 'dictId' },
    isOrigin: boolean = true
  ) {
    const { label, value } = listToOptFilters

    return lst.map((item) => {
      if (isOrigin) {
        return {
          ...item,
          label: item[label],
          value: item[value]
        } as T & ListToOptFilters
      }

      return {
        label: item[label],
        value: item[value]
      } as ListToOptFilters
    })
  }
}
